classdef AbstractMeasurementSession < handle
    %ABSTRACTMEASUREMENTJOB �˴���ʾ�йش����ժ�?
    %   �˴���ʾ��ϸ˵��
    
    properties
        session_name 
        session_description
        session_owner
        
        repository_revision
        repository_status
        start_time
        finish_time
        
        device_file
        device_talbe
        
        control_parameter
        loop_parameter
        
        measurement_data
        
        monitor_fig
        monitor_hdl
    end
    
    methods
        function obj = AbstractMeasurementSession(name)
            obj.session_name = name;
        end
        
        function delete(obj)
            try
                close(obj.monitor_hdl);
            catch
                % monitor does not exist
            end
        end
        
        function obj = close(obj)
            obj.finish_time =  datetime('now');
        end
        
        %% devices
        function initialize_session(obj, devFile)
            if nargin == 1
                devFile = obj.device_file;
            end
            
            obj.device_file = devFile;
            obj.device_talbe = EquipmentControl.AuxiliaryEquipment.Connection.EquipmentConnect(devFile);

%             obj.new_monitor();
            
            info = MeasurementSession.head;
            obj.repository_revision = info.repository_revision;
            obj.repository_status = info.repository_status;            
            obj.start_time = info.start_time;
        end
        
        function create_new_monitor(obj)
            obj.monitor_fig = figure;
            obj.monitor_hdl = axes;
        end
        function close_monitor(obj)
            if isvalid(obj.monitor_fig)
                close(obj.monitor_fig);
            end
        end
        
        function dev = getDevice(obj, var)
            if nargin == 1
%                 obj.listDevice();
                dev = obj.device_talbe.name;
            else
                if isnumeric(var)
                    idx = var;
                elseif ischar(var)
                    idx = find(cellfun(@(x) strcmp(x, var), obj.device_talbe.name));
                end

                try
                    dev = obj.device_talbe.object{idx};
                    type = obj.device_talbe.type{idx};
                catch
                    error('device %d not found.', idx);
                end
                
                if isa(dev, 'EquipmentControl.ZI.ZurichInstruments')
                    dev.session = obj;
                end

                % for execution device
                switch type
                    case {'AOM'}
                        cmd0 = sprintf('%s = obj.getDevice(''%s'');', obj.device_talbe.connection{idx}, obj.device_talbe.connection{idx});
                        cmd = sprintf('dev.controlledBy(%s, %s);', obj.device_talbe.connection{idx}, obj.device_talbe.id{idx});
                        eval([cmd0 cmd]);
                    otherwise
                end
            end
        end
        
        function listDevice(obj)
            devTbl = obj.device_talbe;
            disp(devTbl);
        end
        
        function getAllDevicesInBase(obj, sessionNameStr)
            devNames = obj.device_talbe.name;
            for k = 1:length(devNames)
                cmd = sprintf('%s = %s.getDevice(''%s'');', devNames{k}, sessionNameStr, devNames{k});
                evalin('base', cmd);
            end
        end

        %%
        
        function addDescription(obj, description)
            obj.session_description = description;
        end
        %% parameters
        function addParameter(obj, name, value, unit)
            if nargin == 3
                unit = 'a.u.';
            end
            obj.control_parameter.(name) = {value, unit};
        end
        
        function [val, unit] = getParameter(obj, name)
            val = obj.control_parameter.(name){1};
            unit = obj.control_parameter.(name){2};
        end
        
        function listParam(obj)
            name = fieldnames(obj.control_parameter);
            value = struct2array(obj.control_parameter).';
            paramTbl = table(name, value(1:2:end), value(2:2:end), 'VarAAAiableNames',{'Name', 'Value', 'Unit'});
            
            fprintf('\n################ Parameter infomation ################\n');
            disp(paramTbl);
        end

        function len = makeLoopIndex(obj, varname)
            try 
                val = obj.getParameter(varname);
                len = length(val);
                obj.addParameter('LoopIndex', 1:len);
            catch
                error('Parameter %s not found.', varname);
            end
        end
        
        function len = makeLoopParameter(obj, tag, varName)
            try 
                val = obj.getParameter(varName);
            catch
                error('Parameter %s not found.', varname);
            end
            
            len = length(val);
            obj.loop_parameter.(tag) = num2cell(val);
        end
        
        function val = getLoopParameter(obj, tag, k)
            cellVal = obj.loop_parameter.(tag);
            val = cellVal{k};
        end
        %% data
        function addMeasurementData(obj, tag, data)
            L = log4m.getLogger;
            
            if ~isfield(obj.measurement_data, tag)
                obj.measurement_data.(tag) = [];
            end
            
            if isempty( obj.measurement_data.(tag) )
                obj.measurement_data.(tag) = data;
            else
                obj.measurement_data.(tag) = [obj.measurement_data.(tag), data];
            end
            
            L.info('AbstractMeasurementSession::addMeasurementData', sprintf('Data "%s" stored.', tag) );
        end
        
        function addTemporaryData(obj, data)
            tag = 'TemporaryData';
            obj.measurement_data.(tag) = data; % previous data will be overwritten
        end
        

    end
    
    methods (Abstract)
        run(obj)
        post_process(obj)
    end
    
end

